/*
 * ﻿Copyright (C) 2012-2013 NewMain Softech
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied. See the License for the specific language
 * governing permissions and limitations under the License.
 */
package com.newmainsoftech.ant.types;

import java.lang.reflect.Method;
import java.util.Arrays;

import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.util.JavaEnvUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.ConstructorSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Aspect to inject {@link CommandlineExt} to javaCommand member field and vmCommand member field 
 * of {@link CommandlineJava} object at construction.
 * 
 * @author <a href="mailto:artymt@gmail.com">Arata Y.</a>
 */
@Aspect
public class CommandlineJavaExtAspect {
	Logger logger = LoggerFactory.getLogger( this.getClass());
		protected Logger getLogger() {
			return logger;
		}
		
	@Pointcut( value="initialization( com.newmainsoftech.ant.types.CommandlineJavaExt.new(..))")
	public static void pointcutAtCommandlineJavaExtConstructors() {}
		@AfterReturning( value="pointcutAtCommandlineJavaExtConstructors()")
		public void afterReturningAdvisedCommandlineJavaExtInitialization( JoinPoint joinPoint) 
		throws IllegalAccessException {
			Logger logger = getLogger();
				if ( logger.isDebugEnabled()) {
					ConstructorSignature constructorSignature = (ConstructorSignature)(joinPoint.getSignature());
					logger.debug(
							String.format(
									"Entering constructor: %1$s.",
									constructorSignature.toShortString() 
									)
							);
					logger.debug( 
							String.format(
									"Thead ID: %1$d%nStack-trace to here: %n%2$s",
									Thread.currentThread().getId(),
									Arrays.toString( Arrays.copyOf( Thread.currentThread().getStackTrace(), 10))
									)
							);
				}
			
			CommandlineJavaExt target = (CommandlineJavaExt)(joinPoint.getTarget());
				String targetStr = target.toString();
					if ( logger.isDebugEnabled()) {
						String targetObjStr = null;
							try {
								Method toStringMethod 
								= Object.class.getMethod( "toString", (Class<?>[])null);
									toStringMethod.setAccessible( true);
								targetObjStr 
								= (String)(toStringMethod.invoke( target, (Object[])null));
							}
							catch( Exception exception) { // Ignore
							}
						if ( targetObjStr != null) {
							targetStr
							= String.format(
									"%1$s (for %2$s executable)",
									targetObjStr, target.toString()
									);
						}
					}
			
			CommandlineExt vmCommandValue = new CommandlineExt();
				CommandlineJavaExt.getVmCommandField().set( target, vmCommandValue);
				target.setVm( JavaEnvUtils.getJreExecutable( "java"));
					// Reseted initial executable setting on vmCommand member field since swapped object 
					// of vmCommand member field from Commandline object to CommandlineExt object.
				if ( logger.isDebugEnabled()) {
					logger.debug(
							String.format(
									"Injected %1$s to %2$s member field of %3$s.",
									vmCommandValue, 
									CommandlineJavaExt.getVmCommandField().getName(),
									targetStr
									)
							);
				}
				
				if ( logger.isDebugEnabled()) {
					ConstructorSignature constructorSignature = (ConstructorSignature)(joinPoint.getSignature());
					logger.debug(
							String.format(
									"Exited constructor: ",
									constructorSignature.toShortString() 
									)
							);
				}
			CommandlineExt javaCommandValue = new CommandlineExt();
				CommandlineJavaExt.getJavaCommandField().set( target, javaCommandValue);
				if ( logger.isDebugEnabled()) {
					logger.debug(
							String.format(
									"Injected %1$s to %2$s member field of %3$s.",
									javaCommandValue, 
									CommandlineJavaExt.getJavaCommandField().getName(),
									targetStr
									)
							);
				}
		}
}
